home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
476-500
/
disk_500
/
wiconify
/
wiconify-source.lzh
/
Source
/
wEvent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-19
|
22KB
|
788 lines
/*
* WICONIFY A utility that allows you to iconify any Intuition window
* on any screen, and to open WB windows on any screen.
*
* wEvent.c Main event loop routines.
*
* Copyright 1990 by Davide P. Cervone, all rights reserved.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "wHandler.h"
#include "wMenu.h"
static char *IconAbout = COPYRIGHT; /* ABOUT... message */
static WORD MouseX,MouseY; /* Saved mouse position */
static WSCREEN *MouseScreen = NULL; /* Screen where mouse move occured */
static WICONREF *PressedIcon; /* Icon to report a release event to */
static WICON NullIcon = {NULL, NULL,NULL,NULL, 0,0,0, 0,NULL};
/* an empty icon structure */
extern struct Window *WindowToActivate;
/*
* DoVanillaKey()
*
* Then, if the right amiga key was pressed, and no shift is pressed,
* Attempt to create a new screen of the required depth
* If successful, activate the wIconify window on the screen
*/
static void DoVanillaKey(Code,Qualifier,theWindow)
USHORT Code;
USHORT Qualifier;
struct Window *theWindow;
{
WSCREEN *theScreen;
if (Code >= '1' && Code <= '5')
{
if ((Qualifier & (AMIGARIGHT | SHIFTKEYS)) == AMIGARIGHT)
{
Code -= '0';
theScreen = DoNewScreen(Code,theWindow->WScreen);
if (theScreen && theScreen->BackDrop)
ActivateWindow(theScreen->BackDrop);
}
}
}
/*
* DoMouseButtons()
*
* Do the right thing for each of the event types:
* SELECTDOWN:
* Cancel any drag in progress (never should happen)
* If there are any icons selected, deselect them
*
* SELECTUP:
* If there is an icon to report a release event to, do it
* Complete any dragging that is in progress
* If there is a window to activate (due to a double-click), do it
* (we wait until now so that the window does not get an unexpected
* SELECTUP message when the mouse is released)
*
* MENUDOWN:
* Cancel any dragging in progress
*
* MENUUP:
* Cancel any dragging and close any selected icons (the only time we will
* get menu buttons rather than menu events is when an icon is being
* dragged)
*/
static void DoMouseButtons(theMessage,theScreen)
struct IntuiMessage *theMessage;
WSCREEN *theScreen;
{
switch(theMessage->Code)
{
case SELECTDOWN:
CancelDragging(theScreen);
if (theScreen->Selected) DeselectAll(theScreen);
break;
case SELECTUP:
if (PressedIcon) ReportEvent(WI_REPORTRELEASE,PressedIcon);
EndDragging(theScreen,theMessage->MouseX,theMessage->MouseY);
if (WindowToActivate)
ActivateWindow(WindowToActivate),
WindowToActivate = NULL;
break;
case MENUDOWN:
CancelDragging(theScreen);
break;
case MENUUP:
CancelDragging(theScreen);
CloseSelected(theScreen);
break;
}
PressedIcon = NULL;
}
/*
* DoMouseMove()
*
* If mouse moves have occured,
* If icons are being dragged on the given screen,
* Move them to their new location
* Reset for next move
*/
void DoMouseMove()
{
if (MouseScreen)
{
if (MouseScreen->Flags & (WI_STARTDRAG| WI_DRAGGING))
MoveGels(MouseScreen,MouseX,MouseY);
MouseScreen = NULL;
}
}
/*
* EARLIERTIME checks if one time value is earlier than another.
*/
#define EARLIERTIME(s1,m1,s2,m2) ((s1)<(s2)||((s1)==(s2)&&(m1)<(m2)))
/*
* DoGadgetDown()
*
* If the current message time is earlier than the previous time (ie, the
* clock has been reset), then if the time is not zero (ie, it is not a
* bogus time stamp from some other input handler) then clear the old times
* If we have a double click
* Cancel dragging in progress (never should happen)
* Open the list of selected gadgets, but wait to activate the windows
* until we get a mouse up event
* Otherwise
* If the gadget wants press events reported,
* Report the event and save the pressed gadget for a release event
* Select the pressed gadget
* If the gadget has been selected, set up for dragging it
* Record the time for double click checking.
*/
static void DoGadgetDown(theGadget,theScreen,theMessage)
struct wGadget *theGadget;
WSCREEN *theScreen;
struct IntuiMessage *theMessage;
{
static long Secs = 0, Mics = 0;
if (EARLIERTIME(theMessage->Seconds,theMessage->Micros,Secs,Mics))
if (theMessage->Seconds || theMessage->Micros) Secs = Mics = 0;
if (DoubleClick(Secs,Mics,theMessage->Seconds,theMessage->Micros))
{
CancelDragging(theScreen);
OpenSelected(theScreen,FALSE);
} else {
if (GADGETICON->Icon.Report & WI_REPORTPRESS)
{
ReportEvent(WI_REPORTPRESS,GADGETICON);
PressedIcon = GADGETICON;
}
SelectIcon(GADGETICON,theMessage->Qualifier & SHIFTKEYS);
if (theGadget->Gadget.Flags & SELECTED)
StartDragging(GADGETICON,theMessage->MouseX,theMessage->MouseY);
Secs = theMessage->Seconds;
Mics = theMessage->Micros;
}
}
/*
* DoIconMenu()
*
* Do the right thing for each of the menu items (the routine names are
* pretty self-explanitory).
*/
static int DoIconMenu(theCode,theScreen,EndItAll)
USHORT theCode;
WSCREEN *theScreen;
int EndItAll;
{
switch(ITEMNUM(theCode))
{
case IM_OPEN:
OpenSelected(theScreen,TRUE);
break;
case IM_CLOSE:
CloseSelected(theScreen);
break;
case IM_LOCK:
LockSelected(theScreen);
UpdateActiveMenu();
break;
case IM_CLEANUP:
CleanUpIcons(theScreen);
RefreshIcons(theScreen,TRUE);
break;
case IM_ORGANIZE:
OrganizeIcons(theScreen);
RefreshIcons(theScreen,TRUE);
break;
case IM_OPENALL:
OpenAllIcons(theScreen);
break;
case IM_ABOUT:
if (ActiveWindow)
{
SetWindowTitles(ActiveWindow,-ONE,IconAbout);
ShowTitle(ActiveWindow->WScreen,TRUE);
}
break;
case IM_END:
DoEndIconify();
break;
}
return(EndItAll);
}
/*
* DoMenu()
*
* While there are more menu items to do
* Get the menu item pointer
* If it is an ICON menu item, do the ICON menu code
* Otherwise do the SCREEN menu code
* Go on to the next item
*/
static int DoMenu(theCode,theScreen,EndItAll)
USHORT theCode;
WSCREEN *theScreen;
int EndItAll;
{
struct MenuItem *theItem;
while (theCode != MENUNULL)
{
theItem = ItemAddress(wMenu,theCode);
switch(MENUNUM(theCode))
{
case ICON_MENU:
EndItAll = DoIconMenu(theCode,theScreen,EndItAll);
break;
case SCREEN_MENU:
EndItAll = DoScreenMenu(theCode,theScreen,EndItAll);
break;
}
theCode = theItem->NextSelect;
}
return(EndItAll);
}
/*
* DoEvent()
*
* Clear the ABOUT or error message from the screen title, if necessary
* Get the screen of the wIconify window were the message occured
* If the screen exists
* If there are pending mouse moves and this is not a mouse move
* Do the buffered mouse moves
* Call the correct routine for each class of events
*/
int DoEvent(theMessage,EndItAll)
struct IntuiMessage *theMessage;
int EndItAll;
{
WSCREEN *theScreen;
if (ActiveWindow && ActiveWindow->ScreenTitle != wIconifyTitle)
SetWindowTitles(ActiveWindow,-ONE,wIconifyTitle);
theScreen = (WSCREEN *)theMessage->IDCMPWindow->UserData;
if (theScreen)
{
if (MouseScreen && theMessage->Class != MOUSEMOVE) DoMouseMove();
switch(theMessage->Class)
{
case MOUSEBUTTONS:
DoMouseButtons(theMessage,theScreen);
break;
case GADGETDOWN:
DoGadgetDown(theMessage->IAddress,theScreen,theMessage);
break;
case MENUPICK:
CancelDragging(theScreen);
EndItAll = DoMenu(theMessage->Code,theScreen,EndItAll);
break;
case MOUSEMOVE:
MouseX = theMessage->MouseX;
MouseY = theMessage->MouseY;
MouseScreen = theScreen;
break;
case VANILLAKEY:
DoVanillaKey(theMessage->Code,theMessage->Qualifier,
theMessage->IDCMPWindow);
break;
case ACTIVEWINDOW:
SetActiveWindow(theMessage->IDCMPWindow);
WindowToActivate = NULL;
break;
case INACTIVEWINDOW:
SetActiveWindow(NULL);
WindowToActivate = NULL;
break;
}
}
return(EndItAll);
}
/*
* DoIconify()
*
* Get the icon and screen of the given window
* If the screen was located
* but there was no icon for the window
* Create a new icon structure, if possible
* Make it point to the given window
* Set its default flags and mark it as system-created
* And link it into the icon list for its screen
* If an icon exists or was allocated
* If the icon is for a screen and dragging is in progress (ie, the
* left button is down over an icon), and the message is a NOREPLY
* message (ie, it came from the handler), then
* Close the selected icons on the screen
* Otherwise
* If the icon wants to verify iconifications, report ICONVERIFY
* Otherwise iconify the window
*/
void DoIconify(theMessage)
struct wIconMessage *theMessage;
{
WICONREF *theIcon;
WSCREEN *theScreen;
theIcon = FindIcon(theMessage->Window,&theScreen);
if (theScreen)
{
if (theIcon == NULL)
{
if (NEWSTRUCT(wIconRef,theIcon))
{
theIcon->Window = theMessage->Window;
theIcon->Icon.Flags |= WI_SYSICON | DefaultFlags;
LinkIcon(theIcon,theScreen);
}
}
if (theIcon)
{
if ((theIcon->Icon.Flags & WI_SCREENICON) &&
(theIcon->Screen->Flags & (WI_STARTDRAG | WI_DRAGGING)) &&
(theMessage->Flags & WI_NOREPLY))
{
CloseSelected(theIcon->Screen);
} else {
if (theIcon->Icon.Report & WI_REPORTICONVERIFY)
ReportEvent(WI_REPORTICONVERIFY,theIcon);
else
Iconify(theIcon,theMessage->Flags & WI_CHANGE);
}
}
}
}
/*
* UpdateIcon()
*
* If there was no icon given, use the blank icon
* Get the icon's screen and system flags
* Copy the icon template to the existing icon
* And replace the system flags from before
* If the icon is currently iconified (ie, it has a gadget)
* Get the gadget pointer
* Remove the gadget temprarily so we can work on it
* If no new position was given, retrieve the old one
* Save the SELECTED flag
* Setup the gadget to use the current icon data
* If it used to be selected, re-select it
* Replace the gadget on the screen and refresh the screen's icons
*/
static void UpdateIcon(theIcon,WIcon)
WICONREF *theIcon;
WICON *WIcon;
{
WSCREEN *theScreen;
ULONG Flags;
int pos;
struct Gadget *theGadget;
if (WIcon == NULL) WIcon = &NullIcon;
theScreen = theIcon->Screen;
Flags = theIcon->Icon.Flags & WI_SYSTEMFLAGS;
theIcon->Icon = *WIcon;
theIcon->Icon.Flags = (WIcon->Flags & ~WI_SYSTEMFLAGS) | Flags;
if (theIcon->Gadget)
{
theGadget = &(theIcon->Gadget->Gadget);
if (theScreen->BackDrop)
pos = RemoveGadget(theScreen->BackDrop,theGadget);
if (WIcon->x == 0 && WIcon->y == 0)
theIcon->Icon.x = theGadget->LeftEdge,
theIcon->Icon.y = theGadget->TopEdge;
Flags = theGadget->Flags & SELECTED;
SetupGadget(theIcon);
if (Flags) MakeSelected(theGadget);
if (theScreen->BackDrop) AddGadget(theScreen->BackDrop,theGadget,pos);
RefreshIcons(theScreen,TRUE);
}
}
/*
* DoSetIcon()
*
* Find the icon and screen of the given window
* If the icon already exists, update it to the new values,
* Otherwise, if the screen was found
* Get a new Icon structure, if possible
* Link it to the window
* Copy the data from the template
* Clear the system flags
* If no template was given, add the default flags
* Link the icon to the screen's icon list
* Return the pointer to the IconRef structure
*/
static void DoSetIcon(theWindow,WIcon,theMessage)
struct Window *theWindow;
WICON *WIcon;
struct wIconMessage *theMessage;
{
WICONREF *theIcon;
WSCREEN *theScreen;
theIcon = FindIcon(theWindow,&theScreen);
if (theIcon) UpdateIcon(theIcon,WIcon);
else if (theScreen)
{
if (NEWSTRUCT(wIconRef,theIcon))
{
theIcon->Window = theWindow;
theIcon->Icon = (WIcon)? *WIcon: NullIcon;
theIcon->Icon.Flags &= ~WI_SYSTEMFLAGS;
if (WIcon == NULL) theIcon->Icon.Flags |= DefaultFlags;
LinkIcon(theIcon,theScreen);
}
}
theMessage->Icon = theIcon;
}
/*
* DoUnSetIcon()
*
* Find the icon and screen of the given window
* If the icon was found
* Restore the icon's window and remove the icon from the screen
* Delete the icon from memory
* Return the IconRef (which is no longer valid)
*/
static void DoUnSetIcon(theWindow,theMessage)
struct Window *theWindow;
struct wIconMessage *theMessage;
{
WICONREF *theIcon;
theIcon = FindIcon(theMessage->Window,&(theMessage->Data.wScreen));
if (theIcon)
{
Restore(theIcon,TRUE);
DeleteIcon(theIcon);
}
theMessage->Icon = theIcon;
}
/*
* DoAddIcon()
*
* If a screen and an icon are given
* Create a new Icon structure
* Mark it as having no window associated with it
* Copy the template icon
* Clear the system flags
* Link the icon into the screen's icon list
* Iconify the icon (ie, make it show up on the screen
* Return the newly created IconRef
*/
static WICONREF *DoAddIcon(WIcon,theScreen)
WICON *WIcon;
WSCREEN *theScreen;
{
WICONREF *theIcon = NULL;
if (theScreen && WIcon)
{
if (NEWSTRUCT(wIconRef,theIcon))
{
theIcon->Window = NULL;
theIcon->Icon = *WIcon;
theIcon->Icon.Flags &= ~WI_SYSTEMFLAGS;
LinkIcon(theIcon,theScreen);
Iconify(theIcon,FALSE);
}
}
return(theIcon);
}
/*
* DoSelectNext()
*
* If the screen has selected icons, start with the next one,
* Otherwise start with the first icon on the screen
* Skip over any non-iconified icons
* If we hit the end of the list of icons
* Start over at the begining of the list
* Skip over any non-iconified icons (until we get back to were we started)
* If we found a new icon to select, select it
*/
static void DoSelectNext(theScreen)
WSCREEN *theScreen;
{
WICONREF *theIcon,*InitialIcon;
if (theScreen->Selected)
InitialIcon = ((WICONREF *)(theScreen->Selected->Gadget.UserData))->Next;
else
InitialIcon = theScreen->IconRef;
theIcon = InitialIcon;
while (theIcon && (theIcon->Icon.Flags & WI_ICONIFIED) == FALSE)
theIcon = theIcon->Next;
if (theIcon == NULL)
{
theIcon = theScreen->IconRef;
while (theIcon && (theIcon->Icon.Flags & WI_ICONIFIED) == FALSE &&
theIcon != InitialIcon) theIcon = theIcon->Next;
}
if (theIcon) SelectIcon(theIcon,FALSE);
}
/*
* DoIconEvent()
*
* Do the right thing for each type of message
* ICONIFY: Do the iconification routine
* RESTORE: Restore the given icon
* ICONOF: Find the icon and screen of the given window
* SETICON: Set the window's icon
* UNSETICON: Remove the window's icon
* SELECTICON: Attempt to select the indicated icon
* UNSELECT: Remove the icon from the selection
* MOVEICON:
* If an icon was specified
* Get the icon's screen
* If the icon has a gadget and the screen has a wIconify window
* Remove the gadget from the screen
* Set the gadget's position to the one given in the message
* Check the new position for validity
* Put the gadget back on the screen
* Refresh the icons on the screen
* ADDICON: Add the given icon to the indicated screen
* REMOVEICON: Delete the icon from memory
* REDRAW: Refresh the icons on the given screen
* UPDATEICON: Update the given icon with new values
* BACKDROPOF:
* Find the screen structure if the given screen
* If found, return the backdrop window of the screen
* Otherwise return NULL
* REMSCREEN: Remove the given screen from the list of screens
* CLOSEICON: Close the given icon
* SELECTNEXT: Select the next icon on the given screen
* NEWSCREEN:
* If the real WB screen is open (to use as a template)
* Change the active window (unsetting the menus)
* Set the NewScreen menu to the given modes
* Create the new screen and return its pointer
* MAKEWB:
* Find the indicated screen
* If it is found and it has a wIconify window
* Make this the current WB screen
* Set the OpenWindow submenu to make CURRENT_WB checked
* Activate the new WB screen's wIconify backdrop window
* OPENSELECT: Open the selected icons on the given screen
* CLOSESELECT: Close the selected icons on the given screen
* OPENON: Set the OpenOn menu items
* REPORTVERIFY: (returned ICONVERIFY message)
* If the message was OKed, iconify the window
* MAKECONTACT: (Initial message from the loader)
* Check the loader's version and report OK or BAD
* ENDICONIFY:
* Try to end the process
* Report to any programs that are interested
* Try to exit when we have cleaned out all message from the ports
*/
int DoIconEvent(theMessage,EndItAll)
struct wIconMessage *theMessage;
int EndItAll;
{
WSCREEN *theScreen;
int pos;
switch(theMessage->Action)
{
case WI_ICONIFY:
DoIconify(theMessage);
break;
case WI_RESTORE:
Restore(theMessage->Icon,TRUE);
break;
case WI_ICONOF:
theMessage->Icon =
FindIcon(theMessage->Window,&(theMessage->Data.wScreen));
break;
case WI_SETICON:
DoSetIcon(theMessage->Window,theMessage->Icon,theMessage);
break;
case WI_UNSETICON:
DoUnSetIcon(theMessage->Window,theMessage);
break;
case WI_SELECTICON:
SelectIcon(theMessage->Icon,theMessage->Flags & WI_ADDTOSELECT);
break;
case WI_UNSELECT:
DeselectIcon(theMessage->Icon);
break;
case WI_MOVEICON:
if (theMessage->Icon)
{
theScreen = theMessage->Icon->Screen;
if (theMessage->Icon->Gadget && theScreen->BackDrop)
{
pos = RemoveGadget(theScreen->BackDrop,theMessage->Icon->Gadget);
theMessage->Icon->Gadget->Gadget.LeftEdge =
theMessage->Data.Position.x;
theMessage->Icon->Gadget->Gadget.TopEdge =
theMessage->Data.Position.y;
InitPosition(theMessage->Icon->Gadget);
AddGadget(theScreen->BackDrop,theMessage->Icon->Gadget,pos);
RefreshIcons(theMessage->Icon->Screen,TRUE);
}
}
break;
case WI_ADDICON:
if (theMessage->Icon) theMessage->Icon =
DoAddIcon(theMessage->Icon,FindScreen(theMessage->Data.Screen));
break;
case WI_REMOVEICON:
if (theMessage->Icon) DeleteIcon(theMessage->Icon);
break;
case WI_REDRAW:
RefreshIcons(theMessage->Data.wScreen,TRUE);
break;
case WI_UPDATEICON:
if (theMessage->Icon)
UpdateIcon(theMessage->Icon,theMessage->Data.Icon);
break;
case WI_BACKDROPOF:
theScreen = FindScreen(theMessage->Data.Screen);
if (theScreen)
theMessage->Window = theScreen->BackDrop;
else
theMessage->Window = NULL;
break;
case WI_REMSCREEN:
UnLinkScreen(theMessage->Data.wScreen);
break;
case WI_CLOSEICON:
CloseIcon(theMessage->Icon);
break;
case WI_SELECTNEXT:
theScreen = FindScreen(theMessage->Data.Screen);
if (theScreen) DoSelectNext(theScreen);
break;
case WI_NEWSCREEN:
if (RealWB)
{
SetActiveWindow(NULL);
SetScreenMenu(theMessage->Data.NewScreen.Modes);
theScreen =
DoNewScreen(theMessage->Data.NewScreen.Depth,RealWB->Screen);
theMessage->Data.Screen = theScreen->Screen;
}
break;
case WI_MAKEWB:
theScreen = FindScreen(theMessage->Data.Screen);
if (theScreen && theScreen->BackDrop)
{
NewWBScreen(theScreen);
SetWindowMenu(OW_CURRENTWB,NOCHANGE);
ActivateWindow(theScreen->BackDrop);
}
break;
case WI_OPENSELECT:
OpenSelected(FindScreen(theMessage->Data.Screen),TRUE);
break;
case WI_CLOSESELECT:
CloseSelected(FindScreen(theMessage->Data.Screen));
break;
case WI_OPENON:
SetWindowMenu(theMessage->Data.OpenOn.ScreenType,
theMessage->Data.OpenOn.SizeToFit);
break;
case WI_REPORTICONVERIFY:
if (theMessage->Flags & WI_ICONIFYOK)
Iconify(theMessage->Icon,theMessage->Flags & WI_CHANGE);
break;
case WI_MAKECONTACT:
if (theMessage->Data.Version.Maj > MAJLIBVERS ||
(theMessage->Data.Version.Maj == MAJLIBVERS &&
theMessage->Data.Version.Min >= MINLIBVERS))
{
theMessage->Action = WI_VERSIONOK;
theMessage->Data.Version.Maj = MAJVERSION;
theMessage->Data.Version.Min = MINVERSION;
} else {
theMessage->Action = WI_VERSIONBAD;
}
break;
case WI_ENDICONIFY:
AttemptEnd(theMessage);
ReportMulti(WI_REPORTICONEND,NULL,NULL);
EndItAll = TRUE;
break;
}
return(EndItAll);
}